﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Repository.Models;
using Repository.DBContext;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Crypto.Tls;
using Org.BouncyCastle.Tls;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Internal;
using System.IO.Pipes;
using Repository.Dtos;
//数据库用异步
namespace Repository.Service {
	public class SurveyService {
		
		public async Task<List<Survey>> GetSurveysWithPage(int pageIndex, int pageSize) {
			using (var context = new SurveyDbContext()) {
				return await context.Surveys.Where(s => s.State != EnumSurveyState.NotReleased).Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(s => s.CreatedTime).ToListAsync();
			}
		}

		public async Task<List<Survey>> GetSurveysOfUser(Guid uid, int pageIndex, int pageSize) {
			using (var context = new SurveyDbContext()) {
				return await context.Surveys.Where(s => s.UserId.Equals(uid)).Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(s => s.CreatedTime).ToListAsync();
			}
		}

		public async Task<Survey> GetConcreteSurvey(Guid id) {
			using (var context = new SurveyDbContext()) {
				return await context.Surveys
					.Include(s => s.Questions)
						.ThenInclude(cq => cq.Choices)
					.FirstAsync(x => x.Id.Equals(id));
			}
		}

        public async Task<List<Survey>> GetSurveyByName(string name)
        {
            using (var context = new SurveyDbContext())
            {
                return await context.Surveys.Where(s => s.Name.Contains(name)).Take(10).ToListAsync();
            }
        }


        public async Task<bool> Delete(Guid id) {
			using (var context = new SurveyDbContext()) {
				try {

					var syInDb = context.Surveys.FirstOrDefaultAsync(s => s.Id.Equals(id)).Result;
					context.Surveys.Remove(syInDb);
					await context.SaveChangesAsync();
				}
				catch (Exception ex) {
					Console.WriteLine(ex.Message);
					return false;
				}
			}
			Console.WriteLine("更新，删除成功");
			return true;
		}


		public async Task<Guid> AddNewSurvey(Survey survey) {
			try {
				using (var context = new SurveyDbContext()) {
					survey.Id = Guid.NewGuid();
					survey.CreatedTime = DateTime.Now;
					//存问卷
					await context.Surveys.AddAsync(survey);
					await context.SaveChangesAsync();
					return survey.Id;
				}
			}
			catch (Exception ex) {
				Console.WriteLine($"{ex.Message}\n{ex.StackTrace}\n");
				return Guid.Empty;
			}
		}

		public async Task<bool> AddQuestionsIntoSurvey(Guid surveyId, List<QuestionDto> questionDtos) {
			try {
				using (var context = new SurveyDbContext()) {
					//存问题
					foreach (var question in questionDtos) {
						var q = question.ToQuestion();
						q.SurveyId = surveyId;
						//存选项
						if (q.Type == EnumQuesitonType.SingleChoice) {
							foreach (var c in question.Options) {
								var choice = c.ToChoice();
								choice.QuestionId = q.Id;
								context.Choices.Add(choice);
							}
						}
						context.Questions.Add(q);
					}
					await context.SaveChangesAsync();
					return true;
				}
			}
			catch (Exception ex) {
				Console.WriteLine($"{ex.Message}\n{ex.StackTrace}\n");
				return false;
			}
		}

		public async void AddCompleteSurvey(CompletedSurvey completeSurvey) {
			using (var context = new SurveyDbContext()) {
				await context.CompletedSurveys.AddAsync(completeSurvey);
				await context.SaveChangesAsync();
			}
		}

		public async Task<bool> AddUser(UserCredentialsDto userInfo) {
			using (var context = new SurveyDbContext()) {
				if (context.Users.FirstOrDefault(u => u.Name.Equals(userInfo.UserName)) != null) {
					return false;
				}
				if (userInfo == null) {
					Console.WriteLine("Add Null User");
					return false;
				}
				User u = new User { Name = userInfo.UserName, Password = userInfo.Password };
				await context.AddAsync(u);
				await context.SaveChangesAsync();
				return true;
			}
		}

		public async Task<User>? GetUserByName(string name = "") {
			try {
				using (var db = new SurveyDbContext()) {
					return await db.Users.FirstAsync(u => u.Name.Equals(name));
				}
			}
			catch (Exception ex) {
				Console.WriteLine(ex.Message);
				return null;
			}
		}

		public async Task<bool> SubmitSurvey(AnswerDto answer) {
			using (var context = new SurveyDbContext()) {
				var survey = await context.Surveys.FirstAsync(s => s.Id.Equals(answer.SurveyId));
				if (survey == null) {
					Console.WriteLine($"survey not in db.");
					return false;
				}
				survey.FillNumer++;
				foreach (var answerDto in answer.Answers) {
					try {
						context.ShortAnswers.Add(new ShortAnswer {
							Id = Guid.NewGuid(),
							QuestionId = answerDto.QuestionId,
							//Answer = answerDto.answer.ToString(),
							Answer = answerDto.answer
						});
						//var answer_ = int.Parse(answerDto.answer.ToString());
						//context.ChoiceAnswers.Add(
						//	new ChoiceAnswer {
						//		Id = Guid.NewGuid(),
						//		QuestionId = answerDto.QuestionId,
						//		Answer = answer_,
						//	}
						//);
						//var c = await context.Choices.FirstAsync(q => q.QuestionId.Equals(answerDto.QuestionId) && q.Index == answer_);
						//c.FillNumber++;
					}
					catch (Exception ex) {
						//答案是字符串
						Console.WriteLine($"{ex.Message}\n,Try to convert to String\n");
						//context.ShortAnswers.Add(new ShortAnswer {
						//	Id = Guid.NewGuid(),
						//	QuestionId = answerDto.QuestionId,
						//	Answer = answerDto.answer.ToString(),
						//});
					}
				}
				await context.SaveChangesAsync();
				return true;
			}
		}

		public async Task<SurveyData> GetSurveyData(Guid surveyId) {
			var survey = await GetConcreteSurvey(surveyId);
			if (survey is null) {
				return null;
			}

			SurveyData surveyData = new SurveyData() {
				Decription = survey.Description,
				FillNumber = survey.FillNumer
			};

			foreach (var q in survey.Questions) {
				if (q.Type == EnumQuesitonType.MultiChoice)
					continue;
				Dictionary<int, int> eachNumofChoice = new Dictionary<int, int>();
				foreach (var c in q.Choices) {
					eachNumofChoice.Add(c.Index, c.FillNumber);
				}
				surveyData.QuestionDatas.Add(new QuestionData {
					index = q.Index,
					Description = q.Description,
					NumOfEachChoice = eachNumofChoice
				});
			}

			return surveyData;
		}

		public async Task<bool> DeleteSurvey(Guid id) {
			using (var ctx = new SurveyDbContext()) {
				try {
					//Console.WriteLine(id);
					var rm = ctx.Surveys.FirstOrDefault(s => s.Id.Equals(id));
					if (rm == null) {
						Console.WriteLine("Null");
						return false;
					}
					ctx.Surveys.Remove(rm);
					await ctx.SaveChangesAsync();
					return true;
				}
				catch (Exception ex) {
					Console.WriteLine(ex.Message);
					return false;
				}
			}

		}
	}
}

